#include "renderer.h"
#include "../objects.h"

#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_image.h>

#include <GL/glew.h>

void CRenderer::Init()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	TTF_Init();
	IMG_Init(IMG_INIT_PNG);

	ClearColor.r = ClearColor.g = ClearColor.b = 0.2f;

	matProjection = new Matrix4x4;
	matView = new Matrix4x4;

	matView->Identity();
	matView->Look(0.0f, 5.0f, 150.0f, 0.0f, 0.0f, 0.0f);
}

void CRenderer::LinkWindow(CWindow *Window)
{
	pWindow = Window;
}

void CRenderer::SetDisplayMode(int Width, int Height, int Bpp, Uint32 Flags)
{
	pWindow->SetParams(Width, Height, Bpp, Flags);
	pWindow->Create();

	ChangeDisplaySize(Width, Height);

    glEnable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void CRenderer::ChangeDisplaySize(int Width, int Height)
{
	pWindow->Resize(Width, Height);

	glViewport(0, 0, Width, Height);

	matProjection->Projection(90.0f, (float)Width, (float)Height, 1.0f, 1000.0f);
}

void CRenderer::Render()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	glClearColor(ClearColor.r, ClearColor.g, ClearColor.b, 1.0f);

	for(unsigned int i = 0; i < Objects.size(); ++i)
    {
        RenderObject *pObject = Objects[i];

        if(pObject->GetShaderPointer() != pUsingShader)
        {
            pUsingShader = pObject->GetShaderPointer();
            pUsingShader->Use(true);

            pUsingShader->SetMatrix4("inProj", matProjection->GetTab());
            pUsingShader->SetMatrix4("inView", matView->GetTab());

            pUsingMaterial = NULL;
        }
        if(pObject->GetMaterialPointer() != pUsingMaterial)
        {
            pUsingMaterial = pObject->GetMaterialPointer();

            pObject->UseMaterial();
        }

	    pObject->Render(ObjectPrimitives[i]);
	}

	pUsingShader->Use(false);
	pUsingShader = NULL;
	pUsingMaterial = NULL;
}

void CRenderer::SetClearColor(Color3 col)
{
	ClearColor = col;
}

int CRenderer::AddObject(RenderObject *pNew, GLuint uPrimitive)
{
    Objects.push_back(pNew);
    ObjectPrimitives.push_back(uPrimitive);

    return Objects.size()-1;
}

RenderObject* CRenderer::GetObjectPointer(int nIndex)
{
    return Objects[nIndex];
}

